package com.optimatch.ui.model.beans;

import java.util.ArrayList;
import java.util.List;

import com.optimatch.model.db.DB;
import com.optimatch.model.db.Dico;
import com.optimatch.model.solver.ContrainteHome;
import com.optimatch.model.solver.SolverProbleme;
import com.optimatch.model.solver.Triplet;
import com.optimatch.ui.controler.Controler;
import com.optimatch.ui.controler.observers.SolverObserver;
import com.optimatch.ui.model.exceptions.DataBaseException;

public class Probleme {

    private static String AUTOMATIQUE = "Auto";

	private ListeEquipes listeEquipes;
	private List<ContrainteDeDate> contraintesDates;
	private List<ContrainteDePeriode> contraintesPeriode;
	private DB db;
	private Dico dico;
	
	private double minLat = 100;
	private double maxLat = 0;
	
	private double minLong = 100;
	private double maxLong = 0;

	public Probleme() {
		this.listeEquipes = new ListeEquipes();
		this.db = new DB();
		this.dico = new Dico(db);
		this.contraintesDates = new ArrayList<ContrainteDeDate>();
		this.contraintesPeriode = new ArrayList<ContrainteDePeriode>();
	}

	public boolean ajouterEquipe(String nomEquipe, String nomVille) {
		boolean success = true;
		Ville ville;
		try {
			ville = new Ville(nomVille,this.db);
		} catch (DataBaseException e) {
			ville = new Ville(nomVille,0d,0d);
			success = false;
		}
		Equipe equipe = new Equipe(nomEquipe, ville);
		ajouterEquipe(equipe);
		return success;
	}

	public void ajouterEquipe(Equipe equipe) {
		this.listeEquipes.ajouter(equipe);
	}
	
	public void retirerEquipe(int i) {
		this.listeEquipes.retirer(i);
	}
	
	public void fixerMatchDate(int journee, int eq1, int eq2, boolean domicile) {
		this.contraintesDates.add(new ContrainteDeDate(journee, eq1, eq2, domicile));
		System.out.println(this.contraintesDates);
	}
	
	public void fixerMatchPeriode(int journeeMin, int journeeMax, int eq1, int eq2, boolean domicile) {
		this.contraintesPeriode.add(new ContrainteDePeriode(journeeMin, journeeMax, eq1, eq2, domicile));
		System.out.println(this.contraintesPeriode);
	}

	 public String[][] getMatchFixesTable() {
         String[][] res = new String[listeEquipes.size()][listeEquipes.size()];
         for (int i=0;i<this.contraintesDates.size(); i++) {
                 ContrainteDeDate c = this.contraintesDates.get(i);
                 res[i][0] = listeEquipes.get(c.getEquipe1()).getName();
                 res[i][1] = listeEquipes.get(c.getEquipe2()).getName();
                 res[i][2] = "Journée " + (c.getJournee()+1);
                 if (c.isEquipe1ADomicile())
                         res[i][3] = listeEquipes.get(c.getEquipe1()).getName();
                 else
                         res[i][3] = AUTOMATIQUE;
         }
         return res;
 }
 
 public String[][] getMatchPeriodesTable() {
         String[][] res = new String[listeEquipes.size()][listeEquipes.size()];
         for (int i=0;i<this.contraintesPeriode.size(); i++) {
                 ContrainteDePeriode c = this.contraintesPeriode.get(i);
                 res[i][0] = listeEquipes.get(c.getEquipe1()).getName();
                 res[i][1] = listeEquipes.get(c.getEquipe2()).getName();
                 res[i][2] = "Journée " + (c.getJourneeMin()+1);
                 res[i][3] = "Journée " + (c.getJourneeMax()+1);
                 if (c.isEquipe1ADomicile())
                         res[i][4] = listeEquipes.get(c.getEquipe1()).getName();
                 else
                         res[i][4] = AUTOMATIQUE;
         }
         return res;
 }
	
	public void solve(Controler controler) {
		// Cree la liste de triplets n�c�ssaires � lancer le solveur
		List<Triplet> contraintes = new ArrayList<Triplet>();
		List<ContrainteHome> contraintesHome = new ArrayList<ContrainteHome>();
		
		for (ContrainteDeDate c : this.contraintesDates) {
			contraintes.add(new Triplet(c.getEquipe1(),c.getEquipe2(),c.getJournee()));
			if (c.isEquipe1ADomicile()) {
				contraintesHome.add(new ContrainteHome(c.getEquipe1(),c.getEquipe2(),ContrainteHome.HOME));
			}
		}
		for (ContrainteDePeriode c : this.contraintesPeriode) {
			List<Integer> journees = new ArrayList<Integer>();
			for (int i=c.getJourneeMin();i<=c.getJourneeMax();i++) {
				journees.add(i);
			}
			contraintes.add(new Triplet(c.getEquipe1(),c.getEquipe2(),journees));
			if (c.isEquipe1ADomicile()) {
				contraintesHome.add(new ContrainteHome(c.getEquipe1(),c.getEquipe2(),ContrainteHome.HOME));
			}
		}
		
		// Lance le solveur
		SolverProbleme solver = new SolverProbleme(listeEquipes.size(),contraintes,contraintesHome);
		solver.addObserver(new SolverObserver(controler));
		// Solve and prints the solution
		System.out.println(solver.toString(solver.solve()));
	}


	// Native Getters

	public ListeEquipes getListeEquipes() {
		return listeEquipes;
	}

	public DB getDb() {
		return db;
	}
	
	public Dico getDico() {
		return dico;
	}

//	public static void main(String[] args) {
//		Probleme p = new Probleme();
//		p.plot(0,"MAPS_VILLES");
//	}

//	public void plot(int range,String title) {
//		JFrame frame = getFrame(range,title);
//		frame.pack();
//		frame.setVisible(true);
//	}

//	public JFrame getFrame(int range,String title) {
//		JFrame frame = new JFrame();
//		XYDataset data = createDataset(range);
////		XYZDataset data = createDatasetZ(range);
//		XYItemRenderer renderer = new XYDotRenderer();
////		XYBlockRenderer renderer = new XYBlockRenderer();
////		renderer.setPaintScale(new GrayPaintScale(0.0,1.0));
//		NumberAxis domainAxis = new NumberAxis("Longitude");
//		domainAxis.setRange(minLong,maxLong);
////		System.out.println(minLat + " <= Lat <= " + maxLat);
//		NumberAxis rangeAxis = new NumberAxis("Latitude");
//		rangeAxis.setRange(minLat,maxLat);
////		System.out.println(minLong + " <= Long <= " + maxLong);
//		XYPlot plot = new XYPlot(data, domainAxis, rangeAxis, renderer);
//		JFreeChart chart = new JFreeChart(title,
//				JFreeChart.DEFAULT_TITLE_FONT, plot, true);
//		ChartPanel panel = new ChartPanel(chart, true, true, true, false, true);
//		panel.setPreferredSize(new java.awt.Dimension(500, 270));
//		frame.setContentPane(panel);
//		return frame;
//	}
//
//	private XYDataset createDataset(int range) {
//		final XYSeries series = new XYSeries("Values");
//		double x,y;
//		ArrayList<Double> lats;
//		ArrayList<Double> longs;
//		lats = db.genererListeLat();
//		longs = db.genererListeLong();
//		int length = lats.size();
//		for (int i = 0 ; i < length ; i++) {
//			x = longs.get(i);
//			y = lats.get(i);
//			series.add(x,y);
//			if (x < minLong) {
//				minLong = x;
//			} else if (x > maxLong) {
//				maxLong = x;
//			}
//			if (y < minLat) {
//				minLat = y;
//			} else if (y > maxLat) {
//				maxLat = y;
//			}
//		}
//		return new XYSeriesCollection(series);
//	}

	// Other functions
	public int getNbJournes() {
		return listeEquipes.size() - 1;
	}
	
	public int getNbEquipes() {
		return listeEquipes.size();
	}
	
	public List<ContrainteDeDate> getContraintesDates() {
		return contraintesDates;
	}

	public List<ContrainteDePeriode> getContraintesPeriode() {
		return contraintesPeriode;
	}

	public static void main(String args[]) {
		Probleme p = new Probleme();
		System.out.println(p);
	}
	
}
